﻿package{
	
	
	import de.polygonal.ds.DLinkedList;
	import de.polygonal.ds.DListIterator;
	
	import flash.display.*;
	import flash.events.*;
	
	
	import flash.geom.Matrix;
	import flash.geom.Transform;
	import flash.geom.Point;
	
	
	public class Block extends MovieClip{
		
		var isMoved = false;
		
		var vtPos = {x:0, y:0};
		
		var vtMoveTo = {x:0, y:0};
		
		var fMoveTo:Number;
		var fMoveToSpeed:Number;
		
		var MoveToSpeed:Number = 0;
		
		var isActivated:Boolean = false;
		
		var blockColor:int;
		//0 : B
		//1 : G
		//2 : R
		//3 : Star
		//4 : Stone
		
		var BigBlockType:int = 0;
		//0 : 0
		//1 : "BIG_BLOCKTYPE_0"
		//2 : "BIG_BLOCKTYPE_1"
		//3 : "BIG_BLOCKTYPE_2"
		//4 : "BIG_BLOCKTYPE_3"
		
		var DummyBlock:Boolean = false;
		
		var RightLink:Boolean = false;
		var BottomLink:Boolean = false;
		
		var m_fRotation:Number = 0;
		
		var prevBlockColor:int = 9;
		var prevBigBlockType:int = 9;
		
		private var isMagicBlock:Boolean;
		private var isPinBlock:Boolean;
		private var isRollOver:Boolean;
		private var isChainBlock:Boolean;
		private var isEraserBlock:Boolean;
		
		public var subMC:*;	//block 레벨
		
		var MC_RightLink;
		var MC_DownLink;
		
		var PinMC;
		var PinMCsub;
		
		var EraserMC;
		public var MagicMC;
		var ChainMC;
		
		var Index:int;
		
		var MagicEffectLock:Boolean = false;
		var ChainEffectLock:Boolean = false;
		var BigBlockEffectLock:Boolean = false;
		var EraserEffectLock:Boolean = false;
		var PinEffectLock:Boolean = false;
		
		var vtFixPos:Array = [new Point(0,0),
							  new Point(-BlockMap.BLOCK_WIDTH,0),
							  new Point(-BlockMap.BLOCK_WIDTH,-BlockMap.BLOCK_HEIGHT),
							  new Point(0,-BlockMap.BLOCK_HEIGHT)];
		
		var matTransform:Matrix = new Matrix();
		var matTemp0:Matrix = new Matrix();
		var matTemp1:Matrix = new Matrix();
		var matRotation:Matrix = new Matrix();
		var matTrans2:Matrix;
		var tempMat:Matrix;
		
		var resultMat:Matrix;
		var blockColorRate = [30, 30, 30, 4, 0];
		
		
		public function Block(){
			
			addEventListener(Event.ADDED_TO_STAGE, Init);
			
		}
		
		private function Init(e:Event) {
			
			isMagicBlock = false;
			isPinBlock = false;
			isRollOver = false;
			isChainBlock = false;
			isEraserBlock = false;
			
			blockColor = MakeRandomBlock();
			
			addEventListener(CustomEvent.REMOVE_BLOCK, removeBlockHandler, false, 0, true);
			addEventListener(CustomEvent.REMOVE_BLOCK_BIG, removeBlockBigHandler, false, 0, true);
			addEventListener(CustomEvent.REMOVE_ERASER, removeEraserHandler, false, 0, true);
			addEventListener(CustomEvent.REMOVE_STAR, removeStarHandler, false, 0, true);
			
			removeEventListener(Event.ADDED_TO_STAGE, Init);
		}
		
		
		public function MakeRandomBlock():int{
			try{
			var randomTotal:Number = blockColorRate[0] + blockColorRate[1] + blockColorRate[2] + blockColorRate[3] + blockColorRate[4];
			
			var randomVar = int(Math.random()*randomTotal);
			
			var returnVar:int;
			
			if(0 <= randomVar && randomVar < blockColorRate[0]){
				//R
				returnVar = 0;
			}else if(blockColorRate[0] <= randomVar && randomVar < (blockColorRate[0]+blockColorRate[1])){
				//G
				returnVar = 1;
			}else if(blockColorRate[0]+blockColorRate[1] <= randomVar && randomVar < (blockColorRate[0]+blockColorRate[1]+blockColorRate[2])){
				//B
				returnVar = 2;
			}else if(blockColorRate[0]+blockColorRate[1]+blockColorRate[2] <= randomVar && randomVar < (blockColorRate[0]+blockColorRate[1]+blockColorRate[2]+blockColorRate[3])){
				//star
				returnVar = 3;
			}else if(blockColorRate[0]+blockColorRate[1]+blockColorRate[2]+blockColorRate[3] <= randomVar && randomVar < (blockColorRate[0]+blockColorRate[1]+blockColorRate[2]+blockColorRate[3]+blockColorRate[4])){
				//stone
				returnVar = 4;
			}
			}catch (e:TypeError) {
				trace("Block Error");
				trace(MovieClip(this.root), MovieClip(this.root).currentFrame);
				trace(this.parent);
				trace(MovieClip(this.parent).name);
				return 0;
			}
			
			return returnVar;
		}
		
		public function dispose() {
			
			subMC = null;
			
			MC_RightLink = null;
			MC_DownLink = null;
			
			PinMC = null;
			PinMCsub = null;
			
			EraserMC = null;
			MagicMC = null;
			ChainMC = null;
			
			removeEventListener(CustomEvent.REMOVE_BLOCK, removeBlockHandler);
			removeEventListener(CustomEvent.REMOVE_BLOCK_BIG, removeBlockBigHandler);
		}
		
		private function removeBlockBigHandler(e:CustomEvent) {
			//trace("빅지우기 이벤트");
			
			var Remove:*;
			
			
			//노말블럭이면
			
			if(BigBlockType == 0 && !DummyBlock) {
				switch(blockColor){
					case 0:
					if(isPinBlock) {
						Remove = new Block_Pin_B_Remove();
					} else {
						Remove = new Block_B_S_RemoveBig();
					}
					break;
					case 1:
					if(isPinBlock) {
						Remove = new Block_Pin_G_Remove();
					} else {
						Remove = new Block_G_S_RemoveBig();
						}
					break;
					case 2:
					if(isPinBlock) {
						Remove = new Block_Pin_R_Remove();
					} else {
						Remove = new Block_R_S_RemoveBig();
					}
					break;
					case 3:
					Remove = new Block_Star_S_RemoveBig();
					break;
				}
				
				Remove.x = this.x+250;
				Remove.y = this.y+25;
				Menu_InGame.EffectLevel.addChild(Remove);
				
			}
			
			//빅블럭이면
			if(BigBlockType != 0) {
				switch(blockColor){
					case 0:
					Remove = new Block_B_B_RemoveBig();
					break;
					case 1:
					Remove = new Block_G_B_RemoveBig();
					break;
					case 2:
					Remove = new Block_R_B_RemoveBig();
					break;
					case 3:
					Remove = new Block_Star_B_RemoveBig();
					break;
				}
				
				Remove.x = this.x+250;
				Remove.y = this.y+25;
				Menu_InGame.EffectLevel.addChild(Remove);
							
			}
		}
		
		private function removeEraserHandler(e:CustomEvent) {
			var Remove:*;
			
			Remove = new Block_Eraser_Remove();
			
			Remove.x = this.x+250;
			Remove.y = this.y+25;
			Menu_InGame.EffectLevel.addChild(Remove);
			
		}
		
		private function removeStarHandler(e:CustomEvent) {
			var Remove:*;
			
			Remove = new Block_Star_S_Remove();
			
			Remove.x = this.x+250;
			Remove.y = this.y+25;
			Menu_InGame.EffectLevel.addChild(Remove);
			
		}
		
		private function removeBlockHandler(e:CustomEvent) {
			//자신에게 지워라는 명령이 떨어지면
			//자신의 종류에 따라 remove 이펙트 보여줌
			//trace("지우기 이벤트");
			
			var Remove:*;
			
			
			//노말블럭이면
			
			if(BigBlockType == 0 && !DummyBlock) {
				switch(blockColor){
					case 0:
					if(isPinBlock) {
						Remove = new Block_Pin_B_Remove();
					} else {
						Remove = new Block_B_S_Remove2();
					}
					break;
					case 1:
					if(isPinBlock) {
						Remove = new Block_Pin_G_Remove();
					} else {
						Remove = new Block_G_S_Remove2();
						}
					break;
					case 2:
				if(isPinBlock) {
						Remove = new Block_Pin_R_Remove();
					} else {
						Remove = new Block_R_S_Remove2();
					}
					break;
				}
				//Remove.addEventListener(Event.ENTER_FRAME, say);
				
				Remove.x = this.x+250;
				Remove.y = this.y+25;
				Menu_InGame.EffectLevel.addChild(Remove);
				
			}
			
			//빅블럭이면
			if(BigBlockType != 0) {
				switch(blockColor){
					case 0:
					Remove = new Block_B_B_Remove();
					break;
					case 1:
					Remove = new Block_G_B_Remove();
					break;
					case 2:
					Remove = new Block_R_B_Remove();
					break;
				}
				
				Remove.x = this.x+250;
				Remove.y = this.y+25;
				Menu_InGame.EffectLevel.addChild(Remove);
							
			}
			
		}
		
		private function say(e:Event) {
			trace(this, "Still Alive");
		}
		public function SetLinkBlock(_RLink, _DLink){
			
			MC_RightLink = _RLink;
			MC_DownLink = _DLink;
		}
		
		public function MoveToVertical(Y:Number, Speed:Number){
			
			if(Speed < 0){
				vtMoveTo.y = Y;
				vtPos.y = Y;
				isMoved = true;
				//trace("U");
			}else{
				vtMoveTo.y = Y;
				MoveToSpeed = Speed;
				isMoved = true;
				//trace("D");
			}
		}
		
		public function Update(){
			
			if(!isActivated) return;
			
			//vtMoveTo.y는 SetPos, MoveToVertical에서 설정
			//vtPos.y는 SetPos에서 설정
			fMoveTo = vtMoveTo.y - vtPos.y;
			fMoveToSpeed = MoveToSpeed * 0.0165;
			
			isMoved = false;
			
			if(Math.abs(fMoveTo) > fMoveToSpeed)
			{
				if(vtMoveTo.y > vtPos.y){
					//trace("Down");
					vtPos.y += fMoveToSpeed;
				}else {
					//trace("Up");
					vtPos.y -= fMoveToSpeed;
				}
				isMoved = true;
				
			} else if(fMoveTo != 0){
				//trace("Down complete");
				vtPos.y = vtMoveTo.y;
				isMoved = true;
			}
		

		}
		
		public function DrawLink(){
			
			if(blockColor >= 3) {
				MC_RightLink.visible = false;
				MC_DownLink.visible = false;
				return;
			}
			
			if(m_fRotation != 0) return;
			
			if(RightLink){
				MC_RightLink.visible = true;
				MC_RightLink.gotoAndStop(blockColor+1);
				
			}else{
				MC_RightLink.visible = false;
			}
			
			if(BottomLink){
				MC_DownLink.visible = true;
				MC_DownLink.gotoAndStop(blockColor+1);
			}else{
				MC_DownLink.visible = false;
			}
			
		}
		
		public function Draw(matTrans:Matrix){
			matTransform.identity();
			matTemp0.identity();
			matTemp1.identity();
			matRotation.identity();
			matTrans2 = matTrans;
			
			//DrawLink(matTrans);	//연결고리 그리기
			
			if(DummyBlock) {
				gotoAndStop("dummy");
				return;	//더미블록이면 안그림
			}
			
			if(BigBlockType == 0){	//빅블록이 아니면
				
				matTemp0.translate(-BlockMap.BLOCK_WIDTH/2, -BlockMap.BLOCK_HEIGHT/2);
				matRotation.rotate(m_fRotation);
				matTemp1.translate(BlockMap.BLOCK_WIDTH/2, BlockMap.BLOCK_HEIGHT/2);
				
				tempMat = MultiMat(matTemp0, matRotation);
				matTemp0 = MultiMat(tempMat, matTemp1);
				
				matTransform.translate(vtPos.x, vtPos.y);
				
				matTransform = MultiMat(matTemp0, matTransform);
				
				if(matTrans){
					matTransform = MultiMat(matTransform, matTrans);
				}
				
				
				if(PinEffectLock && this.currentFrame == (blockColor+1) && PinMC.visible){
					PinMC.gotoAndStop("make");
					PinEffectLock = false;
				}
				
				if(EraserEffectLock && this.currentFrame == (blockColor+1) && EraserMC.visible){
					EraserMC.gotoAndStop("make");
					EraserEffectLock = false;
				}
				
				if(this.currentFrame != (blockColor+1)) gotoAndStop(blockColor+1);
				
					
				if(PinMC) PinMC.visible = isPinBlock;
				
				if(EraserMC) EraserMC.visible = isEraserBlock;					
				
				
			}else{	//빅블록이면
				
				//빅블록 회전값 적용하기
				matTemp0.translate(-BlockMap.BLOCK_WIDTH, -BlockMap.BLOCK_HEIGHT);
				matRotation.rotate(m_fRotation);
				matTemp1.translate(BlockMap.BLOCK_WIDTH, BlockMap.BLOCK_HEIGHT);
				
				tempMat = MultiMat(matTemp0, matRotation);
				matTemp0 = MultiMat(tempMat, matTemp1);
				
				
				matTransform.translate(vtPos.x + vtFixPos[GetBigBlockType()-1].x, vtPos.y + vtFixPos[GetBigBlockType()-1].y);
				
				matTransform = MultiMat(matTemp0, matTransform);
				
				if(matTrans){
					matTransform = MultiMat(matTransform, matTrans);
				}
				//이전이랑 빅블록타입이 다르면 => 같으면 안그림
				//회전하면리셋
				
				if(BigBlockEffectLock && this.currentFrame == (blockColor+1+5)){
						subMC.gotoAndStop("make");
						BigBlockEffectLock = false;					
				}
				
				if(this.currentFrame != (blockColor+1+5))
					gotoAndStop(blockColor+1 + 5);
				
				
				//if(MagicMC) MagicMC.visible = isMagicBlock;
				//if(ChainMC) ChainMC.visible = isChainBlock;
				
				if(MagicMC) {
					if(MagicEffectLock){
						MagicMC.gotoAndStop("make");
						MagicEffectLock = false;
					}
				}
				if(ChainMC) {
					if(ChainEffectLock){
						ChainMC.gotoAndStop("make");
						ChainEffectLock = false;
					}
				}
				
				//if(subMC) {
					
				//}
				
				
			}
			
			
			prevBlockColor = blockColor;
			prevBigBlockType = BigBlockType;
			
			this.transform.matrix  = matTransform;
			
			
			
		}
		
		public function DrawPin() {
			
			subMC.gotoAndStop(BlockMap.PointPinIndexArray[blockColor] + 1);
			
		}
		public function MultiMat(m1:Matrix, m2:Matrix):Matrix{
			var resultMat:Matrix = new Matrix();
			
			resultMat.a = m1.a*m2.a		+	m1.b*m2.c;
			resultMat.b = m1.a*m2.b		+	m1.b*m2.d;
			resultMat.tx = m1.a*m2.tx	+	m1.b*m2.ty	+	m1.tx;
			resultMat.c = m1.c*m2.a		+	m1.d*m2.c;
			resultMat.d = m1.c*m2.b		+	m1.d*m2.d;
			resultMat.ty = m1.c*m2.tx	+	m1.d*m2.ty	+	m1.ty;
			
			//trace(resultMat.a, resultMat.b, resultMat.tx);
			//trace(resultMat.c, resultMat.d, resultMat.ty);
			
			return resultMat;
		}

		public function SetPos(_vtPos):void{
			//trace(this.name + " SetPos", _vtPos.x, _vtPos.y);
			
			//vtPos = _vtPos;
			vtPos.x = _vtPos.x;
			vtPos.y = _vtPos.y;
			
			vtMoveTo.x = _vtPos.x;
			vtMoveTo.y = _vtPos.y;
			
			//this.x = vtPos.x;
			//this.y = vtPos.y;
		}
		
		public function Activate(){
			this.visible = true;
			isActivated = true;
		}
		public function Deactivate(){
			//trace(this+" Deactivated");
			
			
			this.visible = false;
			isMagicBlock = false;	//여기서 초기화하는것 맞나?
			isActivated = false;
			isPinBlock = false;
			isChainBlock = false;
			isEraserBlock = false;
			BigBlockType = 0;
			
			if(PinMC) PinMC.visible = false;
			
			if(isRollOver)
				SetRollOut();
			
			if (RightLink || BottomLink)
			{
				RightLink = false;
				BottomLink = false;
				DrawLink();
			}
		}
		public function IsActivate():Boolean{
			
			return isActivated;
		}
		public function IsMoved():Boolean{
			return isMoved;
		}
		public function GetBlockColor():int{
			return blockColor;
		}
		public function SetBlockColor(_BlockColor:int){
			blockColor = _BlockColor;
		}
		
		public function GetBigBlockType():int{
			return BigBlockType;
		}
		public function SetBigBlockType(_BigBlockType:int){
			BigBlockType = _BigBlockType;
		}
		
		public function IsDummyBlock():Boolean{
			return DummyBlock;
		}
		public function SetDummyBlock(_DummyBlock:Boolean){
			DummyBlock = _DummyBlock;
		}
		
		public function SetRotation(_Rotation:Number):void{
			m_fRotation = _Rotation;
		}
		
		public function GetRotation():Number{
			return m_fRotation;
		}
		
		public function SetRightHand(bHand:Boolean){
			RightLink = bHand;
		}
		public function SetBottomHand(bHand:Boolean){
			BottomLink = bHand;
		}
		public function IsRightHand():Boolean{
			return RightLink;
		}
		public function IsBottomHand():Boolean{
			return BottomLink;
		};
		
		public function ResetPrevDrawInfo():void{
			prevBlockColor = 9;
			prevBigBlockType = 9;
			return;
		}
		
		public function SetRollOverStar(_color:int):void{
			//trace("Over Star");
			isRollOver = true;
			subMC.gotoAndStop(_color + 2);
			
		}
		
		public function SetRollOver():void{
			isRollOver = true;
			//빅블록 합쳐지는 애니메이션 중에는 롤오버되도 over로 안가게
			
			if (isPinBlock) {
				PinMC.gotoAndStop("over");
			} else {
				if(subMC){
					subMC.gotoAndStop("over");
				}
			}

			
		}
		
		public function SetRollOut():void {
			isRollOver = false;
			
			if (isPinBlock)
				PinMC.gotoAndStop("normal");
			else {
				if(subMC){
					subMC.gotoAndStop("normal");
				}
			}
		}
		
		public function IsRollOver():Boolean{
			return isRollOver;
		}
		public function SetMagicBlock(_bool:Boolean){
			isMagicBlock = _bool;
		}
		public function GetMagicBlock():Boolean{
			return isMagicBlock;
		}
		public function SetPinBlock(_bool:Boolean) {
			isPinBlock = _bool;

			if(isPinBlock)
				PinMCsub.gotoAndStop(BlockMap.PointPinIndexArray[blockColor] + 1);
		}
		public function IsPinBlock(){
			return isPinBlock;
		}
		public function SetChainBlock(_bool:Boolean){
			isChainBlock = _bool;
		}
		public function GetChainBlock(){
			return isChainBlock;
		}
		public function SetEraserBlock(_bool:Boolean){
			isEraserBlock = _bool;
		}
		public function GetEraserBlock(){
			return isEraserBlock;
		}
		
		public function MagicBlockEffect(){
			MagicEffectLock = true;
		}
		public function ChainBlockEffect(){
			ChainEffectLock = true;
		}
		public function BigBlockEffect(){
			BigBlockEffectLock = true;
		}
		public function EraserEffect(){
			EraserEffectLock = true;
		}
		public function PinEffect(){
			//trace("Pin Effect Set");
			
			PinEffectLock = true;
		}
	}
}